/**
    @author: dt
    @date: 2025-06-23
    @description: 黑板操作任务节点
*/

using UnityEngine;

namespace DLib.BehaviorTree.Tasks
{
    /// <summary>
    /// 设置黑板值任务
    /// 将指定值写入黑板
    /// </summary>
    public class SetBlackboardValueTask<T> : TaskNode
    {
        private Blackboard blackboard;
        private string key;
        private T value;

        public SetBlackboardValueTask(Blackboard blackboard, string key, T value)
        {
            this.blackboard = blackboard;
            this.key = key;
            this.value = value;
        }

        protected override NodeState OnUpdate()
        {
            blackboard.SetValue(key, value);
            return NodeState.Success;
        }
    }

    /// <summary>
    /// 获取黑板值任务
    /// 从黑板读取指定值
    /// </summary>
    public class GetBlackboardValueTask<T> : TaskNode
    {
        private Blackboard blackboard;
        private string key;
        private T defaultValue;
        private T result;

        public GetBlackboardValueTask(Blackboard blackboard, string key, T defaultValue = default(T))
        {
            this.blackboard = blackboard;
            this.key = key;
            this.defaultValue = defaultValue;
        }

        protected override NodeState OnUpdate()
        {
            result = blackboard.GetValue(key, defaultValue);
            return NodeState.Success;
        }

        /// <summary>
        /// 获取读取到的值
        /// </summary>
        public T GetResult()
        {
            return result;
        }
    }

    /// <summary>
    /// 检查黑板值任务
    /// 检查黑板中的值是否满足条件
    /// </summary>
    public class CheckBlackboardValueTask<T> : TaskNode
    {
        private Blackboard blackboard;
        private string key;
        private T expectedValue;
        private System.Func<T, bool> condition;

        /// <summary>
        /// 检查值是否等于期望值
        /// </summary>
        public CheckBlackboardValueTask(Blackboard blackboard, string key, T expectedValue)
        {
            this.blackboard = blackboard;
            this.key = key;
            this.expectedValue = expectedValue;
            this.condition = (value) => Equals(value, expectedValue);
        }

        /// <summary>
        /// 使用自定义条件检查值
        /// </summary>
        public CheckBlackboardValueTask(Blackboard blackboard, string key, System.Func<T, bool> condition)
        {
            this.blackboard = blackboard;
            this.key = key;
            this.condition = condition;
        }

        protected override NodeState OnUpdate()
        {
            if (!blackboard.HasKey(key))
            {
                return NodeState.Failure;
            }

            T value = blackboard.GetValue<T>(key);
            return condition(value) ? NodeState.Success : NodeState.Failure;
        }
    }

    /// <summary>
    /// 检查黑板键是否存在任务
    /// </summary>
    public class CheckBlackboardKeyExistsTask : TaskNode
    {
        private Blackboard blackboard;
        private string key;

        public CheckBlackboardKeyExistsTask(Blackboard blackboard, string key)
        {
            this.blackboard = blackboard;
            this.key = key;
        }

        protected override NodeState OnUpdate()
        {
            return blackboard.HasKey(key) ? NodeState.Success : NodeState.Failure;
        }
    }

    /// <summary>
    /// 删除黑板值任务
    /// </summary>
    public class RemoveBlackboardValueTask : TaskNode
    {
        private Blackboard blackboard;
        private string key;

        public RemoveBlackboardValueTask(Blackboard blackboard, string key)
        {
            this.blackboard = blackboard;
            this.key = key;
        }

        protected override NodeState OnUpdate()
        {
            blackboard.RemoveValue(key);
            return NodeState.Success;
        }
    }

    /// <summary>
    /// 清空黑板任务
    /// </summary>
    public class ClearBlackboardTask : TaskNode
    {
        private Blackboard blackboard;

        public ClearBlackboardTask(Blackboard blackboard)
        {
            this.blackboard = blackboard;
        }

        protected override NodeState OnUpdate()
        {
            blackboard.Clear();
            return NodeState.Success;
        }
    }

    /// <summary>
    /// 调试输出黑板内容任务
    /// </summary>
    public class DebugBlackboardTask : TaskNode
    {
        private Blackboard blackboard;

        public DebugBlackboardTask(Blackboard blackboard)
        {
            this.blackboard = blackboard;
        }

        protected override NodeState OnUpdate()
        {
            blackboard.DebugPrintAll();
            return NodeState.Success;
        }
    }

    // 常用类型的便捷任务类

    /// <summary>
    /// 设置布尔值任务
    /// </summary>
    public class SetBoolTask : SetBlackboardValueTask<bool>
    {
        public SetBoolTask(Blackboard blackboard, string key, bool value) 
            : base(blackboard, key, value) { }
    }

    /// <summary>
    /// 检查布尔值任务
    /// </summary>
    public class CheckBoolTask : CheckBlackboardValueTask<bool>
    {
        public CheckBoolTask(Blackboard blackboard, string key, bool expectedValue) 
            : base(blackboard, key, expectedValue) { }
    }

    /// <summary>
    /// 设置整数值任务
    /// </summary>
    public class SetIntTask : SetBlackboardValueTask<int>
    {
        public SetIntTask(Blackboard blackboard, string key, int value) 
            : base(blackboard, key, value) { }
    }

    /// <summary>
    /// 检查整数值任务
    /// </summary>
    public class CheckIntTask : CheckBlackboardValueTask<int>
    {
        public CheckIntTask(Blackboard blackboard, string key, int expectedValue) 
            : base(blackboard, key, expectedValue) { }
    }

    /// <summary>
    /// 检查整数值范围任务
    /// </summary>
    public class CheckIntRangeTask : CheckBlackboardValueTask<int>
    {
        public CheckIntRangeTask(Blackboard blackboard, string key, int min, int max) 
            : base(blackboard, key, (value) => value >= min && value <= max) { }
    }

    /// <summary>
    /// 设置浮点数值任务
    /// </summary>
    public class SetFloatTask : SetBlackboardValueTask<float>
    {
        public SetFloatTask(Blackboard blackboard, string key, float value) 
            : base(blackboard, key, value) { }
    }

    /// <summary>
    /// 检查浮点数值任务
    /// </summary>
    public class CheckFloatTask : CheckBlackboardValueTask<float>
    {
        public CheckFloatTask(Blackboard blackboard, string key, float expectedValue) 
            : base(blackboard, key, expectedValue) { }
    }

    /// <summary>
    /// 检查浮点数值范围任务
    /// </summary>
    public class CheckFloatRangeTask : CheckBlackboardValueTask<float>
    {
        public CheckFloatRangeTask(Blackboard blackboard, string key, float min, float max) 
            : base(blackboard, key, (value) => value >= min && value <= max) { }
    }

    /// <summary>
    /// 设置字符串任务
    /// </summary>
    public class SetStringTask : SetBlackboardValueTask<string>
    {
        public SetStringTask(Blackboard blackboard, string key, string value) 
            : base(blackboard, key, value) { }
    }

    /// <summary>
    /// 检查字符串任务
    /// </summary>
    public class CheckStringTask : CheckBlackboardValueTask<string>
    {
        public CheckStringTask(Blackboard blackboard, string key, string expectedValue) 
            : base(blackboard, key, expectedValue) { }
    }

    /// <summary>
    /// 检查字符串是否为空任务
    /// </summary>
    public class CheckStringEmptyTask : CheckBlackboardValueTask<string>
    {
        public CheckStringEmptyTask(Blackboard blackboard, string key) 
            : base(blackboard, key, (value) => !string.IsNullOrEmpty(value)) { }
    }

    /// <summary>
    /// 设置Vector3任务
    /// </summary>
    public class SetVector3Task : SetBlackboardValueTask<Vector3>
    {
        public SetVector3Task(Blackboard blackboard, string key, Vector3 value) 
            : base(blackboard, key, value) { }
    }

    /// <summary>
    /// 检查Vector3任务
    /// </summary>
    public class CheckVector3Task : CheckBlackboardValueTask<Vector3>
    {
        public CheckVector3Task(Blackboard blackboard, string key, Vector3 expectedValue) 
            : base(blackboard, key, expectedValue) { }
    }

    /// <summary>
    /// 检查Vector3距离任务
    /// </summary>
    public class CheckVector3DistanceTask : CheckBlackboardValueTask<Vector3>
    {
        public CheckVector3DistanceTask(Blackboard blackboard, string key, Vector3 target, float maxDistance) 
            : base(blackboard, key, (value) => Vector3.Distance(value, target) <= maxDistance) { }
    }

    public enum NumberCompareType 
    {
        Equal,
        NotEqual,
        GreaterThan,
        GreaterThanOrEqual,
        LessThan,
        LessThanOrEqual,
    }

    public class CompareFloatTask : CheckBlackboardValueTask<float>
    {
        public CompareFloatTask(Blackboard blackboard, string key, float compareValue, NumberCompareType compareType) 
            : base(blackboard, key, CreateFloatCondition(compareValue, compareType)) { }

        private static System.Func<float, bool> CreateFloatCondition(float compareValue, NumberCompareType compareType)
        {
            return compareType switch
            {
                NumberCompareType.Equal => (value) => Mathf.Approximately(value, compareValue),
                NumberCompareType.NotEqual => (value) => !Mathf.Approximately(value, compareValue),
                NumberCompareType.GreaterThan => (value) => value > compareValue,
                NumberCompareType.GreaterThanOrEqual => (value) => value >= compareValue,
                NumberCompareType.LessThan => (value) => value < compareValue,
                NumberCompareType.LessThanOrEqual => (value) => value <= compareValue,
                _ => (value) => false
            };
        }
    }

    public class CompareIntTask : CheckBlackboardValueTask<int> 
    {
        public CompareIntTask(Blackboard blackboard, string key, int compareValue, NumberCompareType compareType) 
            : base(blackboard, key, CreateIntCondition(compareValue, compareType)) { }

        private static System.Func<int, bool> CreateIntCondition(int compareValue, NumberCompareType compareType)
        {
            return compareType switch
            {
                NumberCompareType.Equal => (value) => value == compareValue,
                NumberCompareType.NotEqual => (value) => value != compareValue,
                NumberCompareType.GreaterThan => (value) => value > compareValue,
                NumberCompareType.GreaterThanOrEqual => (value) => value >= compareValue,
                NumberCompareType.LessThan => (value) => value < compareValue,
                NumberCompareType.LessThanOrEqual => (value) => value <= compareValue,
                _ => (value) => false
            };
        }
    }

    /// <summary>
    /// 递增整数值任务
    /// </summary>
    public class IncrementIntTask : TaskNode
    {
        private Blackboard blackboard;
        private string key;
        private int increment;

        public IncrementIntTask(Blackboard blackboard, string key, int increment = 1)
        {
            this.blackboard = blackboard;
            this.key = key;
            this.increment = increment;
        }

        protected override NodeState OnUpdate()
        {
            int currentValue = blackboard.GetValue(key, 0);
            blackboard.SetValue(key, currentValue + increment);
            return NodeState.Success;
        }
    }

    /// <summary>
    /// 递减整数值任务
    /// </summary>
    public class DecrementIntTask : TaskNode
    {
        private Blackboard blackboard;
        private string key;
        private int decrement;

        public DecrementIntTask(Blackboard blackboard, string key, int decrement = 1)
        {
            this.blackboard = blackboard;
            this.key = key;
            this.decrement = decrement;
        }

        protected override NodeState OnUpdate()
        {
            int currentValue = blackboard.GetValue(key, 0);
            blackboard.SetValue(key, currentValue - decrement);
            return NodeState.Success;
        }
    }

    /// <summary>
    /// 复制黑板值任务
    /// </summary>
    public class CopyBlackboardValueTask<T> : TaskNode
    {
        private Blackboard blackboard;
        private string sourceKey;
        private string targetKey;
        private T defaultValue;

        public CopyBlackboardValueTask(Blackboard blackboard, string sourceKey, string targetKey, T defaultValue = default(T))
        {
            this.blackboard = blackboard;
            this.sourceKey = sourceKey;
            this.targetKey = targetKey;
            this.defaultValue = defaultValue;
        }

        protected override NodeState OnUpdate()
        {
            T value = blackboard.GetValue(sourceKey, defaultValue);
            blackboard.SetValue(targetKey, value);
            return NodeState.Success;
        }
    }

    /// <summary>
    /// 条件设置黑板值任务
    /// </summary>
    public class ConditionalSetBlackboardValueTask<T> : TaskNode
    {
        private Blackboard blackboard;
        private string key;
        private T value;
        private System.Func<T, bool> condition;

        public ConditionalSetBlackboardValueTask(Blackboard blackboard, string key, T value, System.Func<T, bool> condition)
        {
            this.blackboard = blackboard;
            this.key = key;
            this.value = value;
            this.condition = condition;
        }

        protected override NodeState OnUpdate()
        {
            T currentValue = blackboard.GetValue<T>(key);
            if (condition(currentValue))
            {
                blackboard.SetValue(key, value);
                return NodeState.Success;
            }
            return NodeState.Failure;
        }
    }

    /// <summary>
    /// 获取黑板值数量任务
    /// </summary>
    public class GetBlackboardCountTask : TaskNode
    {
        private Blackboard blackboard;
        private string countKey;

        public GetBlackboardCountTask(Blackboard blackboard, string countKey)
        {
            this.blackboard = blackboard;
            this.countKey = countKey;
        }

        protected override NodeState OnUpdate()
        {
            int count = blackboard.GetKeyCount();
            blackboard.SetValue(countKey, count);
            return NodeState.Success;
        }
    }

    // 便捷的类型特定任务类

    /// <summary>
    /// 复制布尔值任务
    /// </summary>
    public class CopyBoolTask : CopyBlackboardValueTask<bool>
    {
        public CopyBoolTask(Blackboard blackboard, string sourceKey, string targetKey, bool defaultValue = false) 
            : base(blackboard, sourceKey, targetKey, defaultValue) { }
    }

    /// <summary>
    /// 复制整数值任务
    /// </summary>
    public class CopyIntTask : CopyBlackboardValueTask<int>
    {
        public CopyIntTask(Blackboard blackboard, string sourceKey, string targetKey, int defaultValue = 0) 
            : base(blackboard, sourceKey, targetKey, defaultValue) { }
    }

    /// <summary>
    /// 复制浮点数值任务
    /// </summary>
    public class CopyFloatTask : CopyBlackboardValueTask<float>
    {
        public CopyFloatTask(Blackboard blackboard, string sourceKey, string targetKey, float defaultValue = 0f) 
            : base(blackboard, sourceKey, targetKey, defaultValue) { }
    }

    /// <summary>
    /// 复制字符串任务
    /// </summary>
    public class CopyStringTask : CopyBlackboardValueTask<string>
    {
        public CopyStringTask(Blackboard blackboard, string sourceKey, string targetKey, string defaultValue = "") 
            : base(blackboard, sourceKey, targetKey, defaultValue) { }
    }

    /// <summary>
    /// 复制Vector3任务
    /// </summary>
    public class CopyVector3Task : CopyBlackboardValueTask<Vector3>
    {
        public CopyVector3Task(Blackboard blackboard, string sourceKey, string targetKey) 
            : base(blackboard, sourceKey, targetKey, Vector3.zero) { }
        
        public CopyVector3Task(Blackboard blackboard, string sourceKey, string targetKey, Vector3 defaultValue) 
            : base(blackboard, sourceKey, targetKey, defaultValue) { }
    }

    /// <summary>
    /// 条件设置布尔值任务
    /// </summary>
    public class ConditionalSetBoolTask : ConditionalSetBlackboardValueTask<bool>
    {
        public ConditionalSetBoolTask(Blackboard blackboard, string key, bool value, System.Func<bool, bool> condition) 
            : base(blackboard, key, value, condition) { }
    }

    /// <summary>
    /// 条件设置整数值任务
    /// </summary>
    public class ConditionalSetIntTask : ConditionalSetBlackboardValueTask<int>
    {
        public ConditionalSetIntTask(Blackboard blackboard, string key, int value, System.Func<int, bool> condition) 
            : base(blackboard, key, value, condition) { }
    }

    /// <summary>
    /// 条件设置浮点数值任务
    /// </summary>
    public class ConditionalSetFloatTask : ConditionalSetBlackboardValueTask<float>
    {
        public ConditionalSetFloatTask(Blackboard blackboard, string key, float value, System.Func<float, bool> condition) 
            : base(blackboard, key, value, condition) { }
    }
} 